
(function (CloudChat, undefined) {
    CloudChat.Strings = {
        guid : function () {
            var S4 = function () {
                return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
            };
            return (S4() + S4() + '-' + S4() + '-' + S4() + '-' + S4() + '-' + S4() + S4() + S4());
        }
    }
})(window.CloudChat = window.CloudChat || {});



(function (CloudChat, undefined) {
    var EventEmitter = function(){
        this.on = function(eventName,onEvent){
            $(document).on(eventName,function(event){
                var eventArguments = [];

                for(var i = 1; i < event.argumentsLength; i ++){
                    eventArguments.push(event[i]);
                }

                onEvent.apply(this,eventArguments);
            });
        }

        this.removeAllListeners = function(eventName){
            $(document).off(eventName);
        }

        this.emit = function(){
            var event = {
                type : arguments[0],
                argumentsLength : arguments.length
            }

            for(var i = 1; i < arguments.length; i++){
                event[i] = arguments[i];
            }

            $.event.trigger(event);
        }
    }

    var EventManager = function(configuration){
        this.emitter = new EventEmitter();      

        if(EventManager.caller != EventManager.getInstance){
            throw new Error("This object cannot be instanciated");
        }
    };

    EventManager.instance = null;

    EventManager.getInstance = function(){
        if(this.instance === null){
            this.instance = new EventManager();
        }
        return this.instance;
    };

    EventManager.prototype = {
        subscribe : function(eventName,onEvent){
            this.emitter.on(eventName,onEvent);
        },

        unsubscribe : function(eventName){
            this.emitter.removeAllListeners(eventName);
        },

        publish : function(){
            this.emitter.emit.apply(this.emitter,arguments);
        }   
    };

    CloudChat.EventManager = EventManager.getInstance();
})(window.CloudChat = window.CloudChat || {});

(function (CloudChat, undefined) {
    window.googleSignIn = function(authResult){  
        if(authResult && authResult['access_token']){
            gapi.client.load('oauth2', 'v2', function() {
                var request = gapi.client.oauth2.userinfo.get();
                request.execute(function(result){
                    CloudChat.google.loaded({
                        name : result.name,
                        provider : 'google',
                        id : result.id,
                        token : authResult['access_token']
                    });
                });
            });
        }else {
            CloudChat.google.loaded(null);
        }
    }

    CloudChat.google = {
        load : function(callback){
            var po = document.createElement('script'); po.type = 'text/javascript'; po.async = true;
            po.src = 'https://apis.google.com/js/client:plusone.js';
            var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(po, s);               

            CloudChat.google.loaded = callback;

            gapi.auth.authorize({
                client_id: '532324559552.apps.googleusercontent.com',
                cookie_policy: 'single_host_origin',
                scope: 'https://www.googleapis.com/auth/userinfo.profile'
            },googleSignIn);
        }
    }
})(window.CloudChat = window.CloudChat || {});

(function (CloudChat, undefined) {
    CloudChat.guest = {
        load : function(callback){
            callback({
                name : "guest",
                provider : 'guest',
                id : null,
                token : null
            });
        }
    }
})(window.CloudChat = window.CloudChat || {});

(function (CloudChat, undefined) {
    // Additional JS functions here
    window.fbAsyncInit = function() {
        FB.init({
            appId      : '640876879271174', // App ID
            channelUrl : '//howdoyouphil.blogspot.pt', // Channel File
            status     : true, // check login status
            cookie     : true, // enable cookies to allow the server to access the session
            xfbml      : true,  // parse XFBML
            oauth      : true  
        });        

        FB.getLoginStatus(function(response) {
            if (response.status === 'connected') {
                CloudChat.facebook.getUser(response.authResponse.accessToken,function(result){
                    CloudChat.facebook.loaded(result);  
                });                
            } else {
                FB.Event.subscribe('auth.authResponseChange', function(response) {
                    if (response.status !== 'connected') {                
                        FB.login(function(){}, {scope: 'read_stream, email'});
                    }else{
                        window.location = '';
                    }
                });
                CloudChat.facebook.loaded(false);
            }
        });
    };

    CloudChat.facebook = {
        load : function(callback){
            var d = document;
            var js, id = 'facebook-jssdk', ref = d.getElementsByTagName('script')[0];
            if (d.getElementById(id)) {return;}
            js = d.createElement('script'); js.id = id; js.async = true;
            js.src = "//connect.facebook.net/en_US/all.js";
            ref.parentNode.insertBefore(js, ref);  

            CloudChat.facebook.loaded = callback;  
        },

        getUser : function(token,callback){
            FB.api('/me', function(response) {                
                callback({
                    name : response.name,
                    provider : 'facebook',
                    id : response.id,
                    token : token
                });
            });
        }
    }
})(window.CloudChat = window.CloudChat || {});

(function (CloudChat, undefined) {
    Initializer = {
        externalTools: [      
            'https://apis.google.com/js/client.js', 
            'http://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js',
            'https://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.min.js',                        
            'http://code.jquery.com/jquery-2.0.3.min.js',
            'https://storage-cdn.realtime.co/storage/1.0.0/realtime-storage-min.js'
        ],

        internalTools: [ 
        ],

        load: function (callback) {
            Initializer.loadScripts(Initializer.externalTools, function () {
                Initializer.loadScripts(Initializer.internalTools, function () {
                    if(callback) callback();
                });
            });
        },

        loadScript: function (url, callback) {
            var script = document.createElement("script");
            script.type = "text/javascript";

            if (script.readyState) {  //IE
                script.onreadystatechange = function () {
                    if (script.readyState == "loaded" || script.readyState == "complete") {
                        script.onreadystatechange = null;
                        callback();
                    }
                };
            } else {  //Others
                script.onload = function () {
                    callback();
                };
            }
            script.src = url;
            document.getElementsByTagName("head")[0].appendChild(script);
        },

        loadScripts: function (urls, callback) {
            if (urls && urls.length > 0) {
                Initializer.loadScript(urls[urls.length-1], function () {
                    urls.pop();
                    Initializer.loadScripts(urls, callback);
                });
            } else {
                callback();
            }
        }
    };

    Initializer.load(function(){
        setTimeout(function(){ CloudChat.Chat.render(); },100);
    });

    Chat = function(){

    }

    Chat.prototype = {
        loginView : ''
            +   '<div id="chat-loginView" data-ng-controller="CloudChat.UserController" style="text-align: center;display: table;width: 100%; height: 100%; border: 1px solid gray">'
            +   '   <h3 style="display: table-cell; vertical-align: middle;">Login with:</h3>'
            +   '   <div style="display: table-cell; vertical-align: middle;">'
            +   '       <span data-ng-click="login(\'facebook\')" style="cursor: pointer; display: inline-block;padding: 15px; width: 75px; height: 20px;border: 1px solid gray">facebook</span>'
            +   '   </div>'
            +   '   <div style="display: table-cell; vertical-align: middle;">'
            +   '       <span id="googleLoginButton" data-ng-click="login(\'google\')" style="cursor: pointer;display: inline-block;padding: 15px; width: 75px; height: 20px;border: 1px solid gray">google+</span>'
            +   '   </div>'
            +   '   <div style="display: table-cell; vertical-align: middle;">'
            +   '       <span data-ng-click="login(\'guest\')" style="cursor: pointer;display: inline-block;padding: 15px; width: 75px; height: 20px;border: 1px solid gray">guest</span>'
            +   '   </div>'
            +   '</div>'
        + '',

        mainView : ''
            +    '<table id="chat-mainView" style="display: none; width: 100%; height: 100%; border-collapse: collapse; border: 1px solid gray">'
            +    '    <tr style="padding: 0;">'
            +    '        <td style="padding: 0;height: 100%;border: 1px solid gray; vertical-align: bottom;">'
            +    '            <div id="chat-messsages" data-ng-controller="CloudChat.ChatController" style="height: 100%; width: 100%; position: relative;bottom: 0px; overflow: auto;">'
            +    '                <ul style="font-size:14px; list-style-type: none; margin-left: -38px; margin-top: 0px">'                    
            +    '                  <li data-ng-repeat="message in messages">'
            +    '                      {{ message.timestamp | date:"HH:mm:ss" }} <span style="color: blue">{{ message.user }}</span> : {{ message.content }}'
            +    '                  </li>'                    
            +    '                </ul>'                    
            +    '            </div>'
            +    '        </td>'
            +    '        <td data-ng-controller="CloudChat.UsersController" style="padding: 0;width: 150px; border: 1px solid gray; vertical-align:text-top;">'
            +    '          <ul style="list-style-type: none; margin-left: -38px; margin-top: 0px">'                    
            +    '              <li data-ng-repeat="user in users">'
            +    '                  <a target="_blank" style="text-decoration: none; color:inherit;" href="{{ user.link }}">{{ user.name }}</a>'
            +    '              </li>'                    
            +    '          </ul>'  
            +    '        </td>'
            +    '    </tr>'
            +    '    <tr style="padding: 0;" ng-model="user" data-ng-controller="CloudChat.UserController">'
            +    '        <td style="padding: 0; border: 1px solid gray; padding: 0px 2px 0px 2px">'
            +    '            <input id="chat-messagetextbox" ng-model="messageText" placeholder="Type your message here" type="text" style="border: 0px solid; width: 100%; outline: 0; " />'
            +    '        </td>'
            +    '        <td id="chat-sendbutton" data-ng-click="send()" style="padding: 0; border: 1px solid gray;text-align: center; ">'
            +    '            Send'
            +    '        </td>'
            +    '    </tr>'
            +    '    <tr>' 
            +    '        <td data-ng-controller="CloudChat.RoomsController" colspan="2" style="height: 20px">'
            +    '          <ul style="list-style-type: none; margin-left: -30px; margin-top: 0px; padding-right: 32px; padding-left: 32px;">'                    
            +    '              <li class="cloudchatroom" style="cursor: pointer; cursor: hand; border: 1px solid gray; float: left; padding-right: 12px; margin-right: 5px" data-ng-repeat="room in rooms">'
            +    '                  {{ room.name }}'
            +    '              </li>'                    
            +    '          </ul>'
            +    '        </td>'
            +    '    </tr>'
            +    '</table>'
            + '',

        render : function(){
            var angularAppAttribute = $("html").attr("ng-app") || $("html").attr("data-ng-app");
            if (typeof angularAppAttribute === 'undefined' || angularAppAttribute === false) {
                $("html").attr("data-ng-app",""); 
            }

            $("#cloudchatcontainer").html(this.loginView + this.mainView);

            $("#chat-messagetextbox").keyup(function(event){
                if(event.keyCode == 13){
                    $("#chat-sendbutton").click();
                }
            });

            CloudChat.EventManager.subscribe("receivedmessage",function(message){            
                setTimeout(function(){
                    var $target = $('#chat-messsages'); 
                    $target.animate({scrollTop: $target.height()}, 1000);
                },50);
            });

            CloudChat.EventManager.subscribe("loggedin",function(user){
                new CloudChat.RealtimeStorageService({
                    applicationKey: "Ugrahe",
                    authenticationToken: "cloud-chat", 
                });                

                $("#chat-loginView").hide();
                $("#chat-mainView").show();
            });
        }
    }

    CloudChat.Chat = new Chat();

    CloudChat.SecurityService = {
        login : function(provider){
            CloudChat[provider].load(function(loggedUser){
                if(loggedUser){
                    CloudChat.EventManager.publish("loggedin",loggedUser);   
                }                
            }.bind(this));
        }
    }

    CloudChat.RealtimeStorageService = function(configuration){
        var client = Realtime.Storage.create(
            configuration,
            null,
            function(error){
                console.log("Error while loading realtime storage service",error);
            }
        );

        CloudChat.EventManager.subscribe("savemessage",function(message){
            var messagesTableRef = client.table("chat-messages");

            messagesTableRef.push(message,null
            ,function(error){
                console.log("Error in saving message:",error);
            }.bind(this)); 
        }.bind(this));

        CloudChat.EventManager.subscribe("openroom",function(room){
            var messagesTableRef = client.table("chat-messages").equals({item: "room", value: room }).limit(5).asc();

            messagesTableRef.on("put",function(itemSnapshot){            
                if(itemSnapshot && itemSnapshot.val()){
                    CloudChat.EventManager.publish("receivedmessage",itemSnapshot.val());
                }            
            });
        }.bind(this));
    }

    CloudChat.UserController = function($scope){ 
        $scope.user = {};

        CloudChat.EventManager.subscribe("loggedin",function(user){
            $scope.user = user;
        });

        $scope.login = function(provider){
            CloudChat.SecurityService.login(provider);
        };       

        $scope.send = function(){
            CloudChat.EventManager.publish("sendmessage",$scope.messageText);
            $scope.messageText = null;
        }
    }

    CloudChat.ChatController = function($scope){
        $scope.user = {};
        $scope.messages = [];
        $scope.room = "default";

        CloudChat.EventManager.subscribe("loggedin",function(user){
            $scope.user = user;

            CloudChat.EventManager.publish("openroom",$scope.room);
        });

        CloudChat.EventManager.subscribe("sendmessage",function(text){
            var message = {
                content : text,
                user : $scope.user.name,
                userId : $scope.user.id,
                userProvider : $scope.user.provider,
                timestamp : +new Date(),
                room : $scope.room,
                id : CloudChat.Strings.guid() + '-' + (+new Date())
            };
            CloudChat.EventManager.publish("savemessage",message);
        });

        CloudChat.EventManager.subscribe("receivedmessage",function(message){            
            $scope.messages.push(message);
            $scope.messages.sort(function(a,b){
                return a.timestamp-b.timestamp;
            });       
            $scope.$apply(); 
        });
    }

    CloudChat.RoomsController = function($scope){
        $scope.rooms = [
            {
                name : "Room 1",
            },
            {
                name : "Room 2",
            },
            {
                name : "Room 3",
            }
        ];
    }

    CloudChat.UsersController = function($scope){
        $scope.users = [
            {
                name : "User 1",
                link : "http://user1.facebook.com"
            },
            {
                name : "User 2",
                link : "http://user2.facebook.com"
            },
            {
                name : "User 3",
                link : "http://user3.facebook.com"
            }
        ];
    }

})(window.CloudChat = window.CloudChat || {});